/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.prabhu.jeazyprops.encryption;

import com.prabhu.jeazyprops.interfaces.PropsEncrypt;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.crypto.*;
import javax.crypto.spec.DESedeKeySpec;
import sun.misc.BASE64Encoder;

/**
 * 3DES Encryption
 * @author Pinky
 */
public class Tripledes
        implements PropsEncrypt
{

    Cipher decipher;
    Cipher encipher;

    /**
     * Initializes a new Object
     * @param pFile
     */
    public Tripledes( File pFile )
    {
        SecretKey key;
        try
        {
            key = Tripledes.readKey( pFile );
            decipher = Cipher.getInstance( "DESede" );
            decipher.init( Cipher.DECRYPT_MODE, key );
            encipher = Cipher.getInstance( "DESede" );
            encipher.init( Cipher.ENCRYPT_MODE, key );
        }
        catch ( IOException ex )
        {
        }
        catch ( InvalidKeySpecException ex )
        {
        }
        catch ( InvalidKeyException ex )
        {
        }
        catch ( NoSuchAlgorithmException ex )
        {
        }
        catch ( NoSuchPaddingException ex )
        {
        }
    }

    /**
     * Decrypts the String
     * @param str String to be decrypt
     * @return decrypted String
     */
    public String decrypt( String str )
    {
        try
        {
            byte[] decipher1 = new sun.misc.BASE64Decoder().decodeBuffer( str );
            byte[] decryptedBytes = decipher.doFinal( decipher1 );
            return new String( decryptedBytes, "UTF8" );
        }
        catch ( IllegalBlockSizeException ex )
        {
        }
        catch ( BadPaddingException ex )
        {
        }
        catch ( IOException ex )
        {
        }
        return null;
    }

    /**
     * Encrypts the String
     * @param str String to be Encrypt
     * @return Encrypted String
     */
    public String encrypt( String str )
    {
        try
        {
            byte[] encipher1 = str.getBytes( "UTF8" );
            byte[] encrpyedBytes = encipher.doFinal( encipher1 );
            return new BASE64Encoder().encode( encrpyedBytes );
        }
        catch ( UnsupportedEncodingException ex )
        {
        }
        catch ( IllegalBlockSizeException ex )
        {
        }
        catch ( BadPaddingException ex )
        {
        }
        return null;
    }

    /**
     * Generates a DES Key Pass Phrase to File
     * @param pFile Filename to be stored
     */
    public static void generateKeytoFile( String pFile )
    {
        try
        {
            SecretKey key = generateKey();
            Tripledes.writeKey( key, new File( pFile ) );
        }
        catch ( IOException ex )
        {
        }
        catch ( InvalidKeySpecException ex )
        {
        }
        catch ( NoSuchAlgorithmException ex )
        {
        }
    }

    /**
     * Generates a DES Key Pass Phrase
     * @return
     * @throws NoSuchAlgorithmException
     */
    private static SecretKey generateKey()
            throws NoSuchAlgorithmException
    {
        KeyGenerator keygen = KeyGenerator.getInstance( "DESede" );
        return keygen.generateKey();
    }

    /**
     * Writes the key to File
     * @param key Key to be write as file
     * @param f file to be stored
     */
    private static void writeKey( SecretKey key, File f )
            throws IOException,
                   NoSuchAlgorithmException, InvalidKeySpecException
    {
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance( "DESede" );
        DESedeKeySpec keyspec = (DESedeKeySpec) keyfactory.getKeySpec( key,
                                                                       DESedeKeySpec.class );
        byte[] rawkey = keyspec.getKey();
        FileOutputStream out = new FileOutputStream( f );
        out.write( rawkey );
        out.close();
    }

    /**
     * Reads the Pass Phrase from File
     * @param f file to be read
     * @return pass phrase
     */
    private static SecretKey readKey( File f )
            throws IOException,
                   NoSuchAlgorithmException, InvalidKeyException,
                   InvalidKeySpecException
    {
        DataInputStream in = new DataInputStream( new FileInputStream( f ) );
        byte[] rawkey = new byte[(int) f.length()];
        in.readFully( rawkey );
        in.close();
        DESedeKeySpec keyspec = new DESedeKeySpec( rawkey );
        SecretKeyFactory keyfactory = SecretKeyFactory.getInstance( "DESede" );
        SecretKey key = keyfactory.generateSecret( keyspec );
        return key;
    }
}
